package iws.g5.uebung3.impls;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import iws.g5.uebung3.StateModel;
import iws.g5.uebung3.enums.EventType;
import iws.g5.uebung3.enums.OrganicType;
import iws.g5.uebung3.interfaces.LivingOrganicObject;
import iws.g5.uebung3.interfaces.OrganicObject;

/**
 * Cell class
 * @author t.ganzert
 *
 */
public class Cell extends LivingOrganicObject implements OrganicObject {
	static Random rand = new Random();
	
	int noFoodCount;
	
	double cellDivideProbabality = 0.1;
	double infectionProbability = 0.0002;
	double dieOnImmunizationProbability = 0.1;
	
	public Cell(StateModel env, int birthIteration){
		super(env, birthIteration);
		noFoodCount = 0;
	}
	
	/**
	 * Event triggered by the controller
	 */
	public void onEventTriggered(int iteration, EventType event){
		if(event==EventType.CELLDIVISION){
			reproduce(iteration);
		}
		if(event==EventType.IMMUNIZATION) {
			if(rand.nextDouble() < dieOnImmunizationProbability) {
				die();
			}
		}

		if(event==EventType.VIRUSAFFECTION) {
			if(rand.nextDouble() < infectionProbability) {
				env.removeOrganicObject(xPosition, yPosition);
				env.addOrganicObject(new Virus(env, iteration), xPosition, yPosition);
			}
		}
	}

	@Override
	public OrganicType getType() {
		return OrganicType.CELL;
	}
	
	/**
	 * This method is reproducing the cell
	 * @param iteration number of actual iteration
	 */
	public void reproduce(int iteration){
		
		if(tryToFindFood()) {
			noFoodCount = 0;
		} else {
			noFoodCount++;
		}
		
		 if(noFoodCount > 20) {
			die();
		} else {
			if(rand.nextDouble() < cellDivideProbabality) {
				randomCellDivide(iteration);
			}
			//if((iteration-birthIteration)%6 == 0) {
			//	randomCellDivide(iteration);			
			//}			
		}
		
	}

	private void randomCellDivide(int iteration) {
		int deltaX = 0;
		int deltaY = 0;
		switch(rand.nextInt(3)) {
		case 0: deltaX = +1; break;
		case 1: deltaX = -1; break;
		}
		switch(rand.nextInt(3)) {
		case 0: deltaY = +1; break;
		case 1: deltaY = -1; break;
		}
		
		int newX = xPosition + deltaX;
		int newY = yPosition + deltaY;
		if(newX>0 && newY>0 && newX<env.getXDimension() && newY<env.getYDimension() && env.isPositionEmpty(newX, newY)) {
			env.addOrganicObject(new Cell(env, iteration), newX, newY);
		}
	}
	
	private boolean tryToFindFood() {
		for (int x = -1; x <= 1; x++) {
			for (int y = -1; y <=1 ; y++) {
				if(checkFieldForFood(xPosition+x, yPosition+y)) {
					return true;
				}
			}			
		}
		return false;
	}

	private boolean checkFieldForFood(int x, int y) {
		if(x>0 && y>0 && x<env.getXDimension() && y<env.getYDimension() ) {
			OrganicObject object = env.getOrganicObject(x, y);
			if(object != null && object.getType() == (OrganicType.FOOD)) {
				env.removeOrganicObject(x, y);
				return true;
			}
		}
		return false;
	}

}
